﻿using System;
using System.Collections.Generic;

namespace BankSimulation
{
    // 自定义异常：坏钞异常
    public class BadCashException : Exception
    {
        public BadCashException(string message) : base(message) { }
    }

    // 事件参数类：大额取款事件参数
    public class BigMoneyArgs : EventArgs
    {
        public Account Account { get; }
        public decimal Amount { get; }

        public BigMoneyArgs(Account account, decimal amount)
        {
            Account = account;
            Amount = amount;
        }
    }

    // 账户基类
    public class Account
    {
        public string AccountNumber { get; }
        public decimal Balance { get; protected set; }

        public Account(string accountNumber, decimal initialBalance)
        {
            AccountNumber = accountNumber;
            Balance = initialBalance;
        }

        public virtual void Deposit(decimal amount)
        {
            if (amount <= 0)
                throw new ArgumentException("存款金额必须大于0。");

            Balance += amount;
            Console.WriteLine($"账户 {AccountNumber} 存入 {amount} 元，当前余额：{Balance} 元。");
        }

        public virtual void Withdraw(decimal amount)
        {
            if (amount <= 0)
                throw new ArgumentException("取款金额必须大于0。");

            if (amount > Balance)
                throw new InvalidOperationException("余额不足。");

            Balance -= amount;
            Console.WriteLine($"账户 {AccountNumber} 取出 {amount} 元，当前余额：{Balance} 元。");
        }
    }

    // 信用账户类（继承自 Account）
    public class CreditAccount : Account
    {
        public decimal CreditLimit { get; } // 信用额度

        public CreditAccount(string accountNumber, decimal initialBalance, decimal creditLimit)
            : base(accountNumber, initialBalance)
        {
            CreditLimit = creditLimit;
        }

        public override void Withdraw(decimal amount)
        {
            if (amount <= 0)
                throw new ArgumentException("取款金额必须大于0。");

            if (amount > Balance + CreditLimit)
                throw new InvalidOperationException("超过信用额度。");

            Balance -= amount;
            Console.WriteLine($"信用账户 {AccountNumber} 取出 {amount} 元，当前余额：{Balance} 元，信用额度：{CreditLimit} 元。");
        }
    }

    // ATM 类
    public class ATM
    {
        // 定义委托和事件
        public delegate void BigMoneyFetchedEventHandler(object sender, BigMoneyArgs e);
        public event BigMoneyFetchedEventHandler BigMoneyFetched;

        // 取款方法
        public void Withdraw(Account account, decimal amount)
        {
            try
            {
                // 模拟坏钞率 30%
                if (new Random().Next(0, 100) < 30)
                    throw new BadCashException("检测到坏钞，请更换钞票。");

                account.Withdraw(amount);

                // 触发大额取款事件
                if (amount > 10000)
                    BigMoneyFetched?.Invoke(this, new BigMoneyArgs(account, amount));
            }
            catch (BadCashException ex)
            {
                Console.WriteLine($"取款失败：{ex.Message}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"取款失败：{ex.Message}");
            }
        }
    }

    // 主程序
    class Program
    {
        static void Main(string[] args)
        {
            // 创建账户
            Account normalAccount = new Account("123456789", 50000);
            CreditAccount creditAccount = new CreditAccount("987654321", 10000, 5000);

            // 创建 ATM
            ATM atm = new ATM();

            // 注册大额取款事件
            atm.BigMoneyFetched += (sender, e) =>
            {
                Console.WriteLine($"警告：账户 {e.Account.AccountNumber} 大额取款 {e.Amount} 元！");
            };

            // 测试取款
            Console.WriteLine("测试普通账户取款：");
            atm.Withdraw(normalAccount, 2000); // 正常取款
            atm.Withdraw(normalAccount, 15000); // 大额取款

            Console.WriteLine("\n测试信用账户取款：");
            atm.Withdraw(creditAccount, 12000); // 使用信用额度取款

            Console.WriteLine("\n测试坏钞异常：");
            for (int i = 0; i < 5; i++)
            {
                atm.Withdraw(normalAccount, 1000); // 模拟坏钞
            }
        }
    }
}